package cn.ex.de001.common.pool;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
public class PoolHeplExecutor {

  /***
   * 核心线程数
   */
  private static final int CORE_POOL_SIZE = 10;
  /***
   * 最大线程数
   */
  private static final int MAXIMUM_POOL_SIZE = 20;
  /***
   * 线程池维护线程所允许的空闲时间(单位秒)
   */
  private static final long KEEP_ALIVE_TIME = 60L;
  /***
   * 单位
   */
  private static final TimeUnit UNIT = TimeUnit.SECONDS;
  /***
   * 阻塞队列
   */
  private static final BlockingQueue<Runnable> WORK_QUEUE = new LinkedBlockingQueue<>(60);

  /***
   * 静态线程池实例
   */
  private static final ThreadPoolExecutor EXECUTOR;
  static {
    EXECUTOR = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAXIMUM_POOL_SIZE,
            KEEP_ALIVE_TIME,
            UNIT,
            WORK_QUEUE,
            new ThreadPoolExecutor.AbortPolicy()
    );
    log.info("线程池已初始化：核心线程数={}, 最大线程数={}, 线程空闲时间={}秒, 阻塞队列大小={}",
            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, WORK_QUEUE.remainingCapacity());
  }

  /**
   * 获取线程池实例
   * @return 线程池实例
   */
  public static ThreadPoolExecutor getPool() {
    return EXECUTOR;
  }

  /**
   * 正确关闭线程池的方法
   * @param executor 线程池实例
   */
  public static void shutdownExecutorService(ThreadPoolExecutor executor) {
    if (executor != null && !executor.isShutdown()) {
      executor.shutdown();
      log.info("尝试关闭线程池...");
      try {
        if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
          log.warn("线程池关闭超时，强制关闭...");
          executor.shutdownNow();
          // 再次等待线程池终止
          if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
            log.error("线程池未能终止！");
          } else {
            log.info("线程池强制关闭成功。");
          }
        } else {
          log.info("线程池已成功关闭。");
        }
      } catch (InterruptedException ie) {
        log.error("线程池关闭过程中被中断，尝试强制关闭...", ie);
        executor.shutdownNow();
        Thread.currentThread().interrupt(); // 还原线程中断状态
      }
    } else {
      log.warn("线程池已关闭或未初始化！");
    }
  }
}
